package com.yazi.mxz.gather.main.goods;

import java.io.IOException;
import java.net.SocketException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;


import org.apache.http.HttpResponse;
import org.apache.http.ParseException;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.apache.http.util.EntityUtils;
import org.springframework.data.domain.PageRequest;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.yazi.mxz.gather.common.App;
import com.yazi.mxz.gather.common.App.PicObject;
import com.yazi.mxz.gather.entity.enums.ProcessType;
import com.yazi.mxz.gather.entity.http.DuolimiResBody;
import com.yazi.mxz.gather.entity.http.DuolimiResBody4Cat;
import com.yazi.mxz.gather.entity.http.DuolimiResBody4Pic;
import com.yazi.mxz.gather.entity.http.DuolimiResBody.Td;
import com.yazi.mxz.gather.entity.http.DuolimiResBody.Tr;
import com.yazi.mxz.gather.entity.http.DuolimiResBody4Cat.A;
import com.yazi.mxz.gather.entity.repository.ProcessLog;
import com.yazi.mxz.gather.entity.repository.Product;
import com.yazi.mxz.gather.repository.ProcessLogRepository;
import com.yazi.mxz.gather.repository.ProductRepository;

public class DuolimiCn extends Thread {
	
	CloseableHttpAsyncClient httpclient;
	ProcessLogRepository logRepository;
	ProductRepository productRepository;
	ObjectMapper om;
	
	public DuolimiCn() {
		init();
	}
	
	public DuolimiCn(int page) {
		init();
		ProcessLog log = logRepository.findOne(ProcessType.DUOLIMI.ordinal());
		log.setCur((long)page);
		logRepository.save(log);
	}
	
	public void init() {
		
		productRepository = App.context.getBean(ProductRepository.class);
		logRepository = App.context.getBean(ProcessLogRepository.class);
		
		httpclient = HttpAsyncClients.createDefault();
		httpclient.start();
		
		om = new XmlMapper();
		om.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
	}


	@Override
	public void run() {
		try {
			ProcessLog log = logRepository.findOne(ProcessType.DUOLIMI.ordinal());
			update(log.getCur().intValue());
		} catch (Exception e1) {
			e1.printStackTrace();
		}
	}
	
	public void run_bak() {
		
		ProcessLog log = logRepository.findOne(ProcessType.DUOLIMI.ordinal());
		if (null == log) {
			log = new ProcessLog();
			log.setId(ProcessType.DUOLIMI.ordinal());
			log.setCur(1000l);// 从大到小
			log.setEnd(1l);
			log.setCount(0);
			logRepository.insert(log);
		}
		
		//log.setCur(600l);
		//log.setCount(0);
		
		boolean isSocketException = false;
		
		try {
			
			
			while (true) {
				isSocketException = false;
				if (log.getCur() == 0) {
					break;
				}
				
				barcodeInfo(log.getCur());
				
				log.setCur(log.getCur() - 1);
				logRepository.save(log);
			
				sleep(200);
			}
			
		} catch (SocketException e) {
			e.printStackTrace();
			isSocketException = true;
			
		} catch (Exception e1) {
			e1.printStackTrace();
			
		} 
		if (!isSocketException) {
			run();
		} 
	}
	
	private void update(int page) throws ParseException, InterruptedException, ExecutionException, IOException {
		ProcessLog log = logRepository.findOne(ProcessType.DUOLIMI.ordinal());
		log.setCur((long)page);
		logRepository.save(log);
		
		List<Product> list = productRepository.findBySource("www.duolimi.cn", new PageRequest(page, 100));
		Map<String, String> detail;
		for (Product product : list) {
			
			String proId = null, area = null, catName, brandName = null, name = null, spec = null, barcode = null, price = null, pic = null, bigPic = null;
			
			proId = product.getSysRemark().split("\\|")[0];
			detail =  getDetailInfo(proId);
			
			barcode = detail.get("barcode");
			name = detail.get("name");
			catName = detail.get("catName");
			spec= detail.get("spec");
			price= detail.get("price");
			brandName = detail.get("brandName");
			area = detail.get("area");
			pic = detail.get("pic");
			bigPic = detail.get("bigPic");
			
			StringBuffer goodsInfo = new StringBuffer();
			goodsInfo.append("\r\nID:" + proId);
			goodsInfo.append("\r\n条码:" + barcode);
			goodsInfo.append("\r\n名称:" + name);
			goodsInfo.append("\r\n单价:" + price);
			goodsInfo.append("\r\n分类:" + catName);
			goodsInfo.append("\r\n规格:" + spec);
			goodsInfo.append("\r\n品牌:" + brandName);
			goodsInfo.append("\r\n产地:" + area);
			goodsInfo.append("\r\n小图:" + pic);
			goodsInfo.append("\r\n大图:" + bigPic);
			System.out.println(goodsInfo);
			
			App.PicObject picObj = new App.PicObject();
			
			if (null != pic ) {
				App.setPic(pic, picObj);
			}
			if (null != bigPic) {
				App.setPic(bigPic, picObj);
			}
			
			System.out.println("修改: " + barcode + " -> " + name);

			if (null == product.getBigPic()) {
				product.setBigPic(App.saveGoodsBigImageV1(picObj.getBigPic()));
			}
			if (null == product.getMidPic()) {
				product.setMidPic(App.saveGoodsMiddleImageV1(picObj.getMidPic()));
			}
			if (null == product.getPic()) {
				product.setPic(App.saveGoodsImageV1(picObj.getPic()));
			}
			
			
			if (null != area && null == product.getArea()) {
				product.setArea(area);
			}
			if (null != brandName && null == product.getBrandName()) {
				product.setBrandName(brandName);
			}
			if (null != catName && null == product.getCatName()) {
				product.setCatName(catName);
			}
			if (null != name && null == product.getName()) {
				product.setName(name);
			}
			if (null != price && null == product.getPrice()) {
				product.setPrice(price);
			}
			/*if (null != unit && null == product.getUnit()) {
				product.setUnit(unit);
			}*/
			if (null != spec && null == product.getSpec()) {
				product.setSpec(spec);
			}
			
			productRepository.save(product);
		}
		
		if (list.size() > 0) {
			update(page + 1);
		}
	}
	
	private String barcodeInfo(long catId) throws JsonParseException, JsonMappingException,
			IOException, InterruptedException, ExecutionException {
		
		System.out.println("ClassID:" + catId);
		
		final HttpGet req = new HttpGet("http://www.duolimi.cn/ProQuotations.asp?ClassID=" + catId);
		//req.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=gb2312");
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		String body = EntityUtils.toString(res.getEntity(), "gb2312");
		if (body.isEmpty()) {
			System.out.println("无响应内容!");
			return null;
		}		
		
		int startIndex = body.indexOf("<table");
		int endIndex = body.indexOf("</table>") + 8;
		body = body.substring(startIndex, endIndex);
		
		// 此处body样版:
		/*
		<table width="94%" border="0" cellpadding="5" cellspacing="1">
		  <tr>
			<td align="center" class="Line"><span style="font-weight: bold">商品名称</span></td>
			<td width="120" align="center" class="Line"><strong>商品条码</strong></td>
			<td width="120" align="center" class="Line"><strong>商品单位</strong></td>
			<td width="150" align="center" class="Line"><strong>批发价</strong></td>
			<td width="120" align="center" class="Line"><strong>操作</strong></td>
		  </tr>
		
		  <tr onMouseOut="this.style.backgroundColor=''" onMouseOver="this.style.backgroundColor='#F4E9F9'">
			<td align="center" class="Line">卓尔诗婷加纳女王乳木果霜50克</td>
			<td align="center" class="Line">026169067197</td>
			<td align="center" class="Line">50gX2支/组</td>
			<td align="center" class="Line">需会员身份</td>
			<td align="center" class="Line"><a href="UserCart.asp?ScAction=SaveSc&ProID=7620&ProNum=1">购买</a>　<a href="UserIndex.asp?Action=SaveUserFavorites&ProID=7620">收藏</a>　<a href="ProShow.asp?ID=7620">查看详情</a></td>
		  </tr>
		</table>
		*/
		
		
		// System.out.println(body);
		//body = body.replaceAll("\\<a[\\s\\S]{0,200}a\\>", ""); or 
		// 将列内容将按字符串对待
		body = body.replaceAll("\\=\"Line\"\\>", "\\=\"Line\"><![CDATA[");
		body = body.replaceAll("\\<\\/td\\>", "]]></td>");
		// System.out.println(body);
		
		DuolimiResBody duolimi = om.readValue(body, DuolimiResBody.class);
		List<Tr> trs = duolimi.getTrs();
		// 只有标题行
		if (trs.size() == 1) {
			System.out.println("此类型无商品:" + catId);
			return null;
		}
		trs.remove(0);
		
		List<Td> tds;
		String name,barcode,unit,proId;
		for (Tr tr : trs) {
			
			tds = tr.getTds();
			name = tds.get(0).getValue().trim(); // 商品名称
			barcode = tds.get(1).getValue().trim(); // 条形码
			unit = tds.get(2).getValue().trim(); // 单位
			proId = tds.get(4).getValue(); // 其它
			proId = proId.substring(proId.indexOf("SaveSc&ProID=") + 13, proId.indexOf("&ProNum=")); // 站点中的商品ID
			

			if (!productRepository.exists(barcode)) {
				
				System.out.println("添加: " + barcode + name);

				Product product = new Product();

				//product.setArea(items.getCountry());
				product.setBarcode(barcode);
				//product.setBrandName(items.getBrandName());
				//product.setFacCode(items.getFacCode());
				//product.setFacName(items.getFacName());
				product.setIsCheckName(true);
				product.setName(name);
				//product.setSpell(rs.getString("pinyin"));
				//product.setPic(img);
				//product.setPrice(items.getPrice());
				product.setUnit(unit);
				product.setSource("www.duolimi.cn");
				//product.setSpec(items.getSpec());
				//product.setSupplier(items.getSupplier());
				product.setSysRemark(proId + "|" + catId);

				productRepository.insert(product);

			} else {
				
				System.out.println("修改: " + barcode + name);

				Product product = productRepository.findOne(barcode);

				if (null != name && null == product.getName()) {
					product.setName(name);
				}
				if (null != unit && null == product.getUnit()) {
					product.setUnit(unit);
				}
				
				productRepository.save(product);

			}
			
		}

		return body;
	}
	
	public Map<String, String> getDetailInfo(String proId) throws InterruptedException, ExecutionException, ParseException, IOException {

		System.out.println("proId:" + proId);
		
		final HttpGet req = new HttpGet("http://www.duolimi.cn/ProShow.asp?ID=" + proId);
		Future<HttpResponse> future = httpclient.execute(req, null);
		HttpResponse res = future.get();
		
		System.out.println(req.getRequestLine() + "->" + res.getStatusLine());
		
		StringBuffer bodySb = new StringBuffer(EntityUtils.toString(res.getEntity(), "gb2312"));
		if (bodySb.length() == 0) {
			System.out.println("无响应内容!");
			return null;
		}
		
		// 分类相关<span></span>
		String str = "<div class=\"ProTitle\">";
		int start = bodySb.indexOf(str) + str.length();// <div class="ProTitle">
		int end = bodySb.indexOf("</span></div>", start) + 7;// </span></div>
		String catStr = bodySb.substring(start, end)
				.replaceAll("&gt;", "")
				.replaceAll("&", "");
		
		DuolimiResBody4Cat duolimi4Cat = om.readValue(catStr, DuolimiResBody4Cat.class);
		List<A> as = duolimi4Cat.getAs();
		as.remove(0);// 删除"首页"
		String catName = "";
		for (A a : as) {
			catName += (catName.isEmpty() ? "":",") +  a.getText();// 各级分类间用,号
		}
		
		// 图片<div></div>
		start = bodySb.indexOf("<div id=\"ProPic\">");// <div id="ProPic">
		end = bodySb.indexOf("</a></div>", start) + 10;
		String picStr = bodySb.substring(start, end)
				.replaceAll("<br />", "")
				.replaceAll("&", "");
				
		DuolimiResBody4Pic duolimi4Pic = om.readValue(picStr, DuolimiResBody4Pic.class);
		String bigPic = duolimi4Pic.getA().getHref(); // 大图
		bigPic = "http://www.duolimi.cn/" + bigPic;
		String pic = duolimi4Pic.getA().getImgs().get(0).getSrc();// 小图
		pic = "http://www.duolimi.cn/" + pic;
		
		
		// 其它详情
		String area = null, brandName = null, name = null, spec = null, barcode = null, price = null;
		
		
		start = bodySb.indexOf("品　名：");
		start = bodySb.indexOf("<strong>", start) + 8;
		end = bodySb.indexOf("</strong>", start);
		name = bodySb.substring(start, end).trim();// 名称
		
		str = "条形码：";
		start = bodySb.indexOf(str);
		if (start > -1) {
			start += str.length();
			end = bodySb.indexOf("<br />", start);
			barcode = bodySb.substring(start, end).trim();// 条码
		}
		
		str = "产　地：";
		start = bodySb.indexOf(str);
		if (start > -1) {
			start += str.length();
			end = bodySb.indexOf("<br />", start);
			area = bodySb.substring(start, end).trim();// 产地
		}
		
		str = "品　牌：";
		start = bodySb.indexOf(str);
		if (start > -1) {
			start += str.length();
			end = bodySb.indexOf("<br />", start);
			brandName = bodySb.substring(start, end).trim();// 品牌
			if (brandName.equals("其它")) {
				brandName = null;
			}
		}
		
		str = "市场价：";
		start = bodySb.indexOf(str);
		if (start > -1) {
			start += str.length();
			end = bodySb.indexOf("<br />", start);
			price = bodySb.substring(start, end)
					.replaceAll("￥","")
					.replaceAll("元","")
					.trim();// 价格
		}
		
		str = "商品单位：";
		start = bodySb.indexOf(str);
		if (start > -1) {
			start += str.length();
			end = bodySb.indexOf("<br />", start);
			spec = bodySb.substring(start, end);
			
			// 类似：300mlX24罐 或者（300mlX24罐）X1组/箱  只需要 300ml
			end = spec.indexOf("X");
			if (end > -1) {
				spec = spec.substring(0, end);
			}
			spec = spec.replaceAll("（","").replaceAll("）","").trim();// 规格
		}
		
		
		Map<String, String> detail = new HashMap<String, String>();
		detail.put("barcode", barcode);
		detail.put("name", name);
		detail.put("catName", catName);
		detail.put("spec", spec);
		detail.put("price", price);
		detail.put("brandName", brandName);
		detail.put("area", area);
		detail.put("pic", pic);
		detail.put("bigPic", bigPic);
		
		return detail;
	}

}
